# -*- coding: utf-8 -*-
import math


def err_compression(points, err_bound, k):
    total_err = 0

    buffer = []
    acc_err = 0
    p_from = None
    idx = 0
    for p in points:
        if len(buffer) == 0:
            p_from = p
            buffer.append([p, idx])
        else:
            if p_from == buffer[-1][0]:
                buffer.append([p, idx])
            else:
                cur_seg = [p_from, p]
                # print(buffer[-1])

                prev_seg = [p_from, buffer[-1][0]]
                err = segment_dist(prev_seg, cur_seg)
                if acc_err + err <= err_bound:
                    acc_err += err
                    buffer.pop(-1)
                    buffer.append([p, idx])
                else:
                    total_err += acc_err
                    acc_err = 0
                    p_from = buffer[-1][0]
                    buffer.append([p, idx])
                    if len(buffer) > k + 1:
                        buffer.pop(0)
        idx += 1

    if [points[0], 0] not in buffer:
        buffer[0] = [points[0], 0]

    compressed = [p[0] for p in buffer]
    indexes = [p[1] for p in buffer]

    # assert len(buffer) == k + 1
    print(len(buffer), " but ", k + 1)

    return compressed, indexes, total_err


def segment_dist(p, q):
    p0, p1 = p
    q0, q1 = q
    p_center = [(p0[0] + p1[0]) / 2, (p0[1] + p1[1]) / 2]
    q_center = [(q0[0] + q1[0]) / 2, (q0[1] + q1[1]) / 2]
    center_dist = point_dist(p_center, q_center)

    p_vec = [p1[0] - p0[0], p1[1] - p0[1]]
    q_vec = [q1[0] - q0[0], q1[1] - q0[1]]
    sub_vec = [p_vec[0] - q_vec[0], p_vec[1] - q_vec[1]]
    oriental_dist = point_dist(sub_vec, [0, 0])

    cos_of_vec = p_vec[0] * q_vec[0] + p_vec[1] * q_vec[1]
    if 1e-7 >= cos_of_vec >= -1e-7:
        cos_of_vec = 0
    else:
        cos_of_vec = cos_of_vec / point_dist(p0, p1) / point_dist(q0, q1)
    alpha = 1 / (1 + math.exp(-cos_of_vec))
    return alpha * center_dist + (1 - alpha) * oriental_dist


def point_dist(p0, p1):
    x0, y0 = p0
    x1, y1 = p1
    dx = x1 - x0
    dy = y1 - y0
    return math.sqrt(dx * dx + dy * dy)


if __name__ == "__main__":
    # # test seg_dist
    # p0 = [0, 0]
    # p1 = [2, 2]
    # q0 = p0
    # q1 = [2, 0]
    # print(segment_dist([p1, p0], [q1, q0]))

    # test error_compression
    points = [
        [0, 0],
        [1, 1],
        [2, 0],
        [3, 1],
        [4, 2],
        [5, 0]
    ]

    compressed, indexes, err = err_compression(points, 2, 2)
    print(compressed, err)
    # print(indexes)
